// 在上次打劫完一条街道之后和一圈房屋后，小偷又发现了一个新的可行窃的地区。这个地区只有一个入口，我们称之为“根”。 除了“根”之外，每栋房子有且只有一个“父“房子与之相连。一番侦察之后，聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫，房屋将自动报警。

// 计算在不触动警报的情况下，小偷一晚能够盗取的最高金额。

// 示例 1:

// 输入: [3,2,3,null,3,null,1]

//      3
//     / \
//    2   3
//     \   \ 
//      3   1

// 输出: 7 
// 解释: 小偷一晚能够盗取的最高金额 = 3 + 3 + 1 = 7.
// 本题目本身就是动态规划的树形版本，通过此题解，可以了解一下树形问题在动态规划问题解法
// 我们使用爷爷、两个孩子、4 个孙子来说明问题
// 首先来定义这个问题的状态
// 爷爷节点获取到最大的偷取的钱数呢

// 首先要明确相邻的节点不能偷，也就是爷爷选择偷，儿子就不能偷了，但是孙子可以偷
// 二叉树只有左右两个孩子，一个爷爷最多 2 个儿子，4 个孙子
// 根据以上条件，我们可以得出单个节点的钱该怎么算
// 4 个孙子偷的钱 + 爷爷的钱 VS 两个儿子偷的钱 哪个组合钱多，就当做当前节点能偷的最大钱数。这就是动态规划里面的最优子结构

class Solution {
    public int rob(TreeNode root) {
         HashMap<TreeNode, Integer> memo = new HashMap<>();
         return cur(root,memo);
    }
    public int cur(TreeNode root,HashMap<TreeNode, Integer> memo)
    {
        if(root==null) return 0;
        if(memo.containsKey(root))
            return memo.get(root);
        int money = root.val;
        if(root.left!=null)
            money+= cur(root.left.left,memo)+cur(root.left.right,memo);
        if(root.right!=null)
            money+=cur(root.right.left,memo)+cur(root.right.right,memo);
        int result = Math.max(money,cur(root.left,memo)+cur(root.right,memo));
        memo.put(root,result);
        return result;
    }
}